﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ENG.TeachersDiary.Classes;
using ENG.TeachersDiary.Forms;
using ENG.TeachersDiary.Model;

namespace ENG.TeachersDiary
{
  public partial class FrmMain : Form
  {
    public enum eDeleteBehavior
    {
      DeleteFirst,
      DeleteLast
    }

    public class Pair
    {
      public string A;
      public string B;
    }

    public FrmMain()
    {
      InitializeComponent();
    }

    private void FrmMain_Load(object sender, EventArgs e)
    {
      //Program.UpdateProgress("Updating caption...");
      //UpdateCaption();

      //BuildGrid();

      Program.HideProgress();
    }

    private void UpdateCaption()
    {
      var db = Common.DBConn;
      this.Text =
        Properties.Resources.Class + " "
        + Common.GetCurrentClass(db).Title + " - " + Common.GetCurrentSubject(db).Title;
    }

    #region Menu events

    private void seznamStudentůToolStripMenuItem_Click(object sender, EventArgs e)
    {
      FrmStudents f = new FrmStudents();

      f.ShowDialog();

      BuildGrid();
    }

    private void seznamTypůZnámekToolStripMenuItem_Click(object sender, EventArgs e)
    {
      FrmMarkGroups f = new FrmMarkGroups();

      f.ShowDialog();

      BuildGrid();
    }

    private void zapsatZnámkuToolStripMenuItem_Click(object sender, EventArgs e)
    {
      InsertNewMark();
    }

    private void editovatZnámkyStudentaToolStripMenuItem_Click(object sender, EventArgs e)
    {
      EditStudentMarks(null);
    }

    private void zadatZnámkuToolStripMenuItem_Click(object sender, EventArgs e)
    {
      int? s;
      int? mg;
      GetGridLocation(out s, out mg);

      InsertNewMark(s, mg);
    }

    private void editovatZnámkyStudentaToolStripMenuItem1_Click(object sender, EventArgs e)
    {
      int? s;
      int? mg;
      GetGridLocation(out s, out mg);

      EditStudentMarks(s);
    }

    private void zapsatHromadnýVýsledekToolStripMenuItem_Click(object sender, EventArgs e)
    {
      InsertSetOfMarks(null);
    }

    private void InsertSetOfMarks(int? markGroupID)
    {
      FrmInsertSetOfMarks f = new FrmInsertSetOfMarks();

      f.Init(markGroupID);
      f.ShowDialog();

      if (f.DialogResult == System.Windows.Forms.DialogResult.OK)
      {
        var changes = f.GetChangedStudentsIDs();
        BuildGrid(changes);
      }
    }

    private void zapsatSaduZnámekToolStripMenuItem_Click(object sender, EventArgs e)
    {
      int? s;
      int? mg;
      GetGridLocation(out s, out mg);

      InsertSetOfMarks(mg);
    }

    private void seznamStudentůhtmlToolStripMenuItem_Click(object sender, EventArgs e)
    {
      string fileName;
      try
      {
        sfdHtml.ShowDialog();

        fileName = sfdHtml.FileName;
        if (string.IsNullOrEmpty(fileName))
          throw new Exception(Properties.Resources.UsertDidNotChooseFile);

        Exporter.ExportStudentsToHtml(fileName);

        MessageBox.Show(Properties.Resources.ExportSucessfullyDoneTo + " " + fileName + ".",
          Properties.Resources.SavedDialogTitle, MessageBoxButtons.OK, MessageBoxIcon.Information);
      }
      catch (Exception ex)
      {
        MessageBox.Show(Properties.Resources.ExportFailedReason + ex.Message,
          Properties.Resources.ErrorDialogTitle, MessageBoxButtons.OK, MessageBoxIcon.Error);
      }
    }

    private void seznamStudentůToolStripMenuItem1_Click(object sender, EventArgs e)
    {
      string fileName;
      try
      {
        sfdTxt.ShowDialog();

        fileName = sfdTxt.FileName;
        if (string.IsNullOrEmpty(fileName))
          throw new Exception(Properties.Resources.UsertDidNotChooseFile);

        Exporter.ExportStudentsToTxt(fileName);

        Common.OpenExplorerForFile(fileName);

        MessageBox.Show(Properties.Resources.ExportSucessfullyDoneTo + fileName + ".",
          Properties.Resources.SavedDialogTitle, MessageBoxButtons.OK, MessageBoxIcon.Information);


      }
      catch (Exception ex)
      {
        MessageBox.Show(Properties.Resources.ExportFailedReason + ex.Message,
          Properties.Resources.ErrorDialogTitle, MessageBoxButtons.OK, MessageBoxIcon.Error);
      }
    }

    private void známkyTřídyToolStripMenuItem_Click(object sender, EventArgs e)
    {
      string fileName;
      try
      {
        sfdHtml.ShowDialog();

        fileName = sfdHtml.FileName;
        if (string.IsNullOrEmpty(fileName))
          throw new Exception(Properties.Resources.UsertDidNotChooseFile);

        Exporter.ExportClassMarksToHtml(fileName);

        Common.OpenExplorerForFile(fileName);

        MessageBox.Show(Properties.Resources.ExportSucessfullyDoneTo + " " + fileName + ".",
          Properties.Resources.SavedDialogTitle, MessageBoxButtons.OK, MessageBoxIcon.Information);
      }
      catch (Exception ex)
      {
        MessageBox.Show(Properties.Resources.ExportFailedReason + ex.Message,
          Properties.Resources.ErrorDialogTitle, MessageBoxButtons.OK, MessageBoxIcon.Error);
      }
    }

    private void známkyStudentahtmlToolStripMenuItem_Click(object sender, EventArgs e)
    {
      string fileName;
      try
      {
        sfdHtml.ShowDialog();

        fileName = sfdHtml.FileName;
        if (string.IsNullOrEmpty(fileName))
          throw new Exception(Properties.Resources.UsertDidNotChooseFile);

        int? studentId = null;
        int? markGroupId = null;
        GetGridLocation(out studentId, out markGroupId);

        if (!studentId.HasValue)
          throw new Exception(Properties.Resources.NoStudentSelectedInList);

        Exporter.ExportStudentMarksToHtml(
          studentId.Value,
          fileName);

        Common.OpenExplorerForFile(fileName);

        MessageBox.Show(Properties.Resources.ExportSucessfullyDoneTo + " " + fileName + ".",
          Properties.Resources.SavedDialogTitle, MessageBoxButtons.OK, MessageBoxIcon.Information);
      }
      catch (Exception ex)
      {
        MessageBox.Show(Properties.Resources.ExportFailedReason + ex.Message,
          Properties.Resources.ErrorDialogTitle, MessageBoxButtons.OK, MessageBoxIcon.Error);
      }
    }

    private void seznamZnámekToolStripMenuItem_Click(object sender, EventArgs e)
    {
      FrmMarkCodes f = new FrmMarkCodes();

      f.ShowDialog();

      BuildGrid();
    }

    private void nastaveníToolStripMenuItem_Click(object sender, EventArgs e)
    {
      string db = Properties.Settings.Default.DBFile;

      FrmOptions f = new FrmOptions();

      f.ShowDialog();

      if (db != Properties.Settings.Default.DBFile)
        Application.Restart();

    }

    private void změnitTřídupředmětToolStripMenuItem_Click(object sender, EventArgs e)
    {
      FrmIntro f = new FrmIntro();

      f.ShowDialog();

      if (f.DialogResult == System.Windows.Forms.DialogResult.OK)
      {
        Common.CurrentClassID = f.SelectedClass.ClassID;
        Common.CurrentSubjectID = f.SelectedSubject.SubjectID;

        this.Init();
      }
    }

    private void konecToolStripMenuItem_Click(object sender, EventArgs e)
    {
      Application.Exit();
    }

    private void zálohovatDBToolStripMenuItem_Click(object sender, EventArgs e)
    {
      Common.DoBackup();
    }

    private void zmenšitPísmoToolStripMenuItem_Click(object sender, EventArgs e)
    {
      float newSize =
      System.Math.Max(grd.Font.Size - 1, 5);

      Font f =
      new Font(grd.Font.FontFamily, newSize);

      grd.Font = f;
    }

    private void zvětšitPísmoToolStripMenuItem_Click(object sender, EventArgs e)
    {
      float newSize =
      System.Math.Min(grd.Font.Size + 1, 18);

      Font f =
      new Font(grd.Font.FontFamily, newSize);

      grd.Font = f;
    }

    private void zkratkyVZáhlavíSloupcůToolStripMenuItem_Click(object sender, EventArgs e)
    {
      BuildGrid();
    }

    #endregion Menu events

    #region Grid building and methos
    private void GetGridLocation(out int? studentID, out int? markGroupID)
    {
      studentID = null;
      markGroupID = null;

      DataGridViewCell cell = grd.CurrentCell;

      string colId = cell.OwningColumn.DataPropertyName;
      if (colId.StartsWith(Model.MarkGroup.COLUMN_PREFIX))
      {
        colId = colId.Substring(Model.MarkGroup.COLUMN_PREFIX.Length);
        markGroupID = int.Parse(colId);
      }

      DataGridViewRow row = cell.OwningRow;
      studentID = int.Parse((string)row.Cells[0].Value);
    }

    private void grd_MouseDoubleClick(object sender, MouseEventArgs e)
    {
      int? studentID = null;
      int? markGroupID = null;

      GetGridLocation(out studentID, out markGroupID);
      if (!studentID.HasValue || !markGroupID.HasValue)
        return;

      if (e.Button == System.Windows.Forms.MouseButtons.Left)
      {
        InsertNewMark(studentID, markGroupID);
      }
      else if (e.Button == System.Windows.Forms.MouseButtons.Right)
        EditStudentMarks(studentID);
    }

    private void InsertNewMark()
    {
      InsertNewMark(null, null);
    }

    private void InsertNewMark(int? studentID, int? markGroupID)
    {
      FrmInsertMark f = new FrmInsertMark();
      f.Init(studentID, markGroupID);
      f.ShowDialog();

      if (f.DialogResult == System.Windows.Forms.DialogResult.OK)
      {
        var changedStudentID = f.GetChangedStudentIDs();
        BuildGrid(changedStudentID);
      }

    }

    private void EditStudentMarks(int? studentID)
    {
      FrmEditStudentsMarks f = new FrmEditStudentsMarks();
      f.Init(studentID);
      f.ShowDialog();

      var ch = f.GetChangetStudentsIDs();

      BuildGrid(ch);
    }

    private void BuildGridColumns()
    {
      grd.Columns.Clear();

      DataGridViewColumn c = null;

      c = BuildGridColumn("StudentID", "StudentID", false);
      c.Visible = false;
      c = BuildGridColumn("Surname", Properties.Resources.SurnameGridColumn, true);
      c.Frozen = true;
      c = BuildGridColumn("Name", Properties.Resources.NameGridColumn, true);
      c.Frozen = true;

      var db = Common.DBConn;
      var mgs = Common.GetCurrentMarkGroups(db);

      foreach (Model.MarkGroup fItem in mgs)
      {
        if (fItem.IsToOffer)
        {
          c = BuildGridColumn(fItem.GetUniqueDescriptor(), fItem.ExtTitle, false);
          if (zkratkyVZáhlavíSloupcůToolStripMenuItem.Checked)
            c.HeaderText = fItem.Abbr;

          c.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
        }
      }

      c = BuildGridColumn("_sumResultMean", Properties.Resources.MeanGridColumn, false);
      c.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
      if (zkratkyVZáhlavíSloupcůToolStripMenuItem.Checked)
        c.HeaderText = Properties.Resources.MeanAbbrGridColumn;
      c = BuildGridColumn("_sumResultDisplay", Properties.Resources.DisplayMarkGridColumn, false);
      c.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
      if (zkratkyVZáhlavíSloupcůToolStripMenuItem.Checked)
        c.HeaderText = Properties.Resources.DisplayMarkAbbrGridColumn;
    }

    private DataGridViewColumn BuildGridColumn(string property, string headerText, bool canSort)
    {
      DataGridViewColumn ret = new DataGridViewColumn()
      {
        DataPropertyName = property,
        HeaderText = headerText,
        ReadOnly = true,
        ValueType = typeof(string),
        SortMode = (canSort ? DataGridViewColumnSortMode.Automatic : DataGridViewColumnSortMode.NotSortable),
        CellTemplate = new DataGridViewTextBoxCell()
      };

      grd.Columns.Add(ret);

      return ret;
    }

    private void BuildGridDataTable(StudentResultCollection studentResultCol)
    {
      DataTable dt = new DataTable();

      dt.Columns.Add("StudentID");
      dt.Columns.Add("Name");
      dt.Columns.Add("Surname");

      if (studentResultCol.Count > 0)
      {
        for (int i = 0; i < studentResultCol[0].Results.Count; i++)
        {
          dt.Columns.Add(
            studentResultCol[0].Results[i].MarkGroup.GetUniqueDescriptor());
        }
      }

      dt.Columns.Add("_sumResultMean");
      dt.Columns.Add("_sumResultDisplay");

      foreach (var fItem in studentResultCol)
      {
        DataRow row = dt.NewRow();

        row["StudentID"] = fItem.Student.StudentID;
        row["Name"] = fItem.Student.Name;
        row["Surname"] = fItem.Student.Surname;

        foreach (MarkGroupResult xItem in fItem.Results)
        {
          row[xItem.MarkGroup.GetUniqueDescriptor()] = xItem.DisplayMarksString;
        }

        if (fItem.SumResult != null)
        {
          row["_sumResultMean"] = fItem.SumResult.Value.ToString(Properties.Settings.Default.NumberFormat);
          row["_sumResultDisplay"] = GetMarkMeanDisplayForValue(fItem.SumResult.Value);
        }

        dt.Rows.Add(row);

      } // foreach (var fItem in studentResultCol)

      grd.AutoGenerateColumns = false;
      grd.DataSource = dt;
    }

    private string GetMarkMeanDisplayForValue(double meanValue)
    {
      string ret = "";
      ENG.TeachersDiary.Model.MeanMeaning lastValid = null;

      var means = Common.CurrentMeanMeanings;

      foreach (var fItem in means)
      {
        if (meanValue <= fItem.MaxMeanValue)
        {
          lastValid = fItem;
          break;
        }
        //else
        //break;
      } // foreach (var fItem in means)

      if (lastValid != null)
        ret = lastValid.Display;

      return ret;
    }

    #region Calculation of student results in background thread



    private StudentResultCollection backgroundlyCalculateStudentResultCollection = null;
    private bool isBackgroundCalculationOfStudentsResultDone = false;

    private void CalculateStudentResultInBgThread()
    {

      System.Threading.ThreadStart ts = new System.Threading.ThreadStart(
        this.CalculateStudentResultsThisIsBackgroundRunningMethod);
      System.Threading.Thread t = new System.Threading.Thread(ts);

      isBackgroundCalculationOfStudentsResultDone = false;

      t.Start();

      while (!isBackgroundCalculationOfStudentsResultDone)
        Application.DoEvents();

    }
    private void CalculateStudentResultsThisIsBackgroundRunningMethod()
    {
      backgroundlyCalculateStudentResultCollection = StudentResultCollection.CreateDefault2();
      isBackgroundCalculationOfStudentsResultDone = true;
    }

    #endregion Calculation of student results in background thread


    private void BuildGrid()
    {
      Program.ShowProgress();

      CalculateStudentResultInBgThread();
      StudentResultCollection col = backgroundlyCalculateStudentResultCollection;

      Program.UpdateProgress(Properties.Resources.BuildingGrid);
      BuildGridColumns();
      BuildGridDataTable(col);

      grd.Sort(grd.Columns[grd.GetPropertyRowIndex("Surname")], ListSortDirection.Ascending);

      AdjustGridWidth();

      Program.HideProgress();
    }

    private void BuildGrid(IEnumerable<int> studentsIDs)
    {
      var db = Common.DBConn;
      var currentSubject = Common.GetCurrentSubject(db);

      foreach (var item in studentsIDs)
      {
        var student = db.Students.First(i => i.StudentID == item);

        StudentResult sr = StudentResult.Create(student, currentSubject);

        UpdateGridData(sr);
      }

      AdjustGridWidth();
    }

    private void BuildGrid (int studentId)
    {
      BuildGrid(new List<int>() { studentId });
    }

    private void UpdateGridData(StudentResult sr)
    {
      DataTable dt = null;
      dt = grd.DataSource as DataTable;
      DataRow row = null;

      for (int i = 0; i < dt.Rows.Count; i++)
      {
        if ((string)dt.Rows[i]["StudentID"] == sr.Student.StudentID.ToString())
        {
          row = dt.Rows[i];
          break;
        }
      }

      if (row == null) throw new Exception(Properties.Resources.FailedToFindStudentException);

      row["StudentID"] = sr.Student.StudentID;
      row["Name"] = sr.Student.Name;
      row["Surname"] = sr.Student.Surname;

      foreach (MarkGroupResult xItem in sr.Results)
      {
        row[xItem.MarkGroup.GetUniqueDescriptor()] = xItem.DisplayMarksString;
      }

      if (sr.SumResult != null)
      {
        row["_sumResultMean"] = sr.SumResult.Value.ToString(Properties.Settings.Default.NumberFormat);
        row["_sumResultDisplay"] = sr.SumResult.Display;
      }
      else
      {
        row["_sumResultMean"] = "";
        row["_sumResultDisplay"] = "";
      }
    }

    private void AdjustGridWidth()
    {
      grd.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
      grd.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.DisplayedCells;
    }
    #endregion Grid building and methos

    public void Init()
    {
      UpdateCaption();

      BuildGrid();
    }

    private void continousSumCalculationToolStripMenuItem_Click(object sender, EventArgs e)
    {
      Properties.Settings.Default.ContinousSumCalc = continousSumCalculationToolStripMenuItem.Checked;
      if (continousSumCalculationToolStripMenuItem.Checked)
        BuildGrid();
    }

    private void recoverFromFastBackupToolStripMenuItem_Click(object sender, EventArgs e)
    {
      if (DialogResult.Yes == MessageBox.Show(
      Properties.Resources.QuickBackupRestoreQuestion,
      Application.ProductName, MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2))
      {
        Common.RestoreQuitBackup();
      }
    }

    private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
    {
      StringBuilder sb = new StringBuilder();

      sb.AppendLine(Application.ProductName);
      sb.AppendLine();
      sb.AppendLine(Application.CompanyName);
      sb.AppendLine();
      sb.AppendLine(Application.ProductVersion.ToString());
      sb.AppendLine(
      System.Diagnostics.FileVersionInfo.GetVersionInfo(
      System.Reflection.Assembly.GetExecutingAssembly().Location).FileVersion.ToString());

      MessageBox.Show(sb.ToString(), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);
    }

    private void listOfMeanMeaningsToolStripMenuItem_Click(object sender, EventArgs e)
    {
      Forms.FrmMeanMeanings f = new Forms.FrmMeanMeanings();

      f.ShowDialog();

      if (continousSumCalculationToolStripMenuItem.Checked)
        BuildGrid();
    }

    private void copyDatabaseToolStripMenuItem_Click(object sender, EventArgs e)
    {
      string source;
      string target;

      if (ofd.ShowDialog() != System.Windows.Forms.DialogResult.OK)
        return;
      if (sfd.ShowDialog() != System.Windows.Forms.DialogResult.OK)
        return;

      source = ofd.FileName;
      target = sfd.FileName;

      DoCopy(source, target);
    }

    #region DB copy

    private void DoCopy(string source, string target)
    {
      throw new NotSupportedException();
    }



    #endregion DB copy

    private void renameCurrentSchoolYearToolStripMenuItem_Click(object sender, EventArgs e)
    {
      var db = Common.DBConn;
      var currentClass = Common.GetCurrentClass(db);

      string newName = FrmInput.ShowDialog(
        Properties.Resources.Renaming,
        Properties.Resources.EnterNewSchoolYearName,
        currentClass.SchoolYear.Title);

      if (
      (newName == null)
      ||
      (newName == currentClass.SchoolYear.Title))
        return;

      currentClass.SchoolYear.Title = newName;
      db.SubmitChanges();
    }

    private void renameCurrentClassToolStripMenuItem_Click(object sender, EventArgs e)
    {
      var db = Common.DBConn;
      var currentClass = Common.GetCurrentClass(db);

      string newName = FrmInput.ShowDialog(
      Properties.Resources.Renaming,
      Properties.Resources.EnterNewClassName,
      currentClass.Title);

      if (
      (newName == null)
      ||
      (newName == currentClass.Title))
        return;

      currentClass.Title = newName;
      db.SubmitChanges();
    }

    private void changeSubjectsNameToolStripMenuItem_Click(object sender, EventArgs e)
    {
      var db = Common.DBConn;
      var currentSubject = Common.GetCurrentSubject(db);


      string newName = FrmInput.ShowDialog(
      Properties.Resources.Renaming,
      Properties.Resources.EnterNewSubjectName,
      currentSubject.Title);

      if (
      (newName == null)
      ||
      (newName == currentSubject.Title))
        return;

      currentSubject.Title = newName;
      db.SubmitChanges();
    }

    private void changeSubjectsAbbreviationToolStripMenuItem_Click(object sender, EventArgs e)
    {
      var db = Common.DBConn;
      var currentSubject = Common.GetCurrentSubject(db);

      string newName = FrmInput.ShowDialog(
        Properties.Resources.Renaming,
        Properties.Resources.EnterNewSubjectAbbr,
        currentSubject.Abbr);

      if (
      (newName == null)
      ||
      (newName == currentSubject.Abbr))
        return;

      currentSubject.Abbr = newName;
      db.SubmitChanges();
    }

    private void enableDirectMarkInsertingToolStripMenuItem_Click(object sender, EventArgs e)
    {
      enableDirectMarkInsertingToolStripMenuItem.Checked =
      !enableDirectMarkInsertingToolStripMenuItem.Checked;
    }

    private void grd_KeyDown(object sender, KeyEventArgs e)
    {
      if (enableDirectMarkInsertingToolStripMenuItem.Checked == false)
        return;

      bool deleteFirst = false;

      switch (e.KeyCode)
      {
        case Keys.Delete:
          deleteFirst = Properties.Settings.Default.DeleteKeyDeletesFirst;
          break;
        case Keys.Back:
          deleteFirst = Properties.Settings.Default.BackspaceKeyDeletesFirst;
          break;
        default:
          return;
      }

      var currentCell = grd.CurrentCell;
      var db = Common.DBConn;

      int? studentId;
      int? markGroupId;
      GetGridLocation(out studentId, out markGroupId);

      if (studentId == null) return;
      if (markGroupId == null) return;

      ENG.TeachersDiary.Model.Mark mark = GetLastMarkIdToDelete(db, studentId.Value, markGroupId.Value, deleteFirst);
      if (mark == null) return;

      var dr = MessageBox.Show(Properties.Resources.ConfirmDirectDeleteQuestion,
         Application.ProductName, MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);

      if (dr != System.Windows.Forms.DialogResult.Yes)
        return;

      db.Marks.DeleteOnSubmit(mark);
      db.SubmitChanges();

      BuildGrid(studentId.Value);
    }

    private ENG.TeachersDiary.Model.Mark GetLastMarkIdToDelete(DiaryDB db, int studentId, int markGroupId, bool deleteFirst)
    {
      ENG.TeachersDiary.Model.Mark ret = null;

      IQueryable<Model.Mark> mrks = null;

      if (deleteFirst)
        mrks = db.Marks.Where(i => i.StudentID == studentId && i.MarkGroupID == markGroupId)
      .OrderBy(i => i.Date).OrderBy(i => i.MarkID);
      else
        mrks = db.Marks.Where(i => i.StudentID == studentId && i.MarkGroupID == markGroupId)
        .OrderByDescending(i => i.Date).OrderByDescending(i => i.MarkID);

      if (mrks.Count() == 0)
        return null;

      ENG.TeachersDiary.Model.Mark m = mrks.ToArray()[0];

      ret = m;

      return ret;
    }

    private void InsertDirectMark(int studentId, int markGroupId, int markCodeId)
    {
      DiaryDB db = Common.DBConn;

      Model.Mark m = new Model.Mark();
      m.StudentID = studentId;
      m.MarkGroupID = markGroupId;
      m.MarkCodeID = markCodeId;
      m.Date = DateTime.Now;

      db.Marks.InsertOnSubmit(m);
      db.SubmitChanges();

      BuildGrid(studentId);
    }

    private int? GetMarkValueFromKey(char keys)
    {
      var mcs = Common.MarkCodes;

      foreach (var fItem in mcs)
      {
        if (fItem.ShortcutChar != null && fItem.ShortcutChar[0] == keys)
          return fItem.MarkCodeID;
      } // foreach (var fItem in mcs)

      return null;
    }

    private bool isGrdKeyPressInProgress = false;
    private void grd_KeyPress(object sender, KeyPressEventArgs e)
    {
      if (enableDirectMarkInsertingToolStripMenuItem.Checked == false)
        return;

      if (isGrdKeyPressInProgress) return;
      isGrdKeyPressInProgress = true;

      var currentCell = grd.CurrentCell;

      int? studentId;
      int? markGroupId;
      GetGridLocation(out studentId, out markGroupId);

      int? markValueId = GetMarkValueFromKey(e.KeyChar);

      if (studentId != null
        &&
        markGroupId != null
        &&
        markValueId != null)
      {
        InsertDirectMark(studentId.Value, markGroupId.Value, markValueId.Value);
      }

      isGrdKeyPressInProgress = false;
    }
  }
}
